package com.api.shopapi.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSONObject;
import com.api.shopapi.entity.*;
import com.api.shopapi.mapper.NurseAideMapper;
import com.api.shopapi.mapper.NurseMapper;
import com.api.shopapi.mapper.StaffMapper;
import com.api.shopapi.mapper.UserMapper;
import com.api.shopapi.service.InstitutionStaffRelService;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.io.FileUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@RestController
@RequestMapping("ImportNurseAideIns")
public class ImportNurseAideInsController extends BaseController {


    @Value("${my.templates.nurseAide}")
    protected String importElderly;

    @Value("${my.thread}")
    protected String path;

    @Value("${my.filesRootPath}")
    protected String filesRootPath;


    @Autowired
    @Qualifier("InstitutionStaffRelServiceImplOne")
    private InstitutionStaffRelService institutionStaffRelService;



    //老人模板表下载
    @RequestMapping(value = "Template", method = RequestMethod.GET)
    public MyResult Template(@RequestParam("timeStr") String timeStr,
                             @RequestParam("sign") String sign,
                             @RequestParam("staffCode") String staffCode,
                             HttpServletResponse response) {

        try {

            PreCheck preCheck =checkSignAdmInterface(timeStr, sign,staffCode,"/ImportExcel/GetElderlyTemplate");
            if(preCheck.getError()==1){
                return failed(preCheck.getMessage());
            }

            ClassPathResource classPathResource = new ClassPathResource(importElderly);
            InputStream inputStream = classPathResource.getInputStream();
            File somethingFile = File.createTempFile("医生模板下载", ".xlsx");
            FileUtils.copyInputStreamToFile(inputStream, somethingFile);
            String templateFileName = somethingFile.getAbsolutePath();
            response.setCharacterEncoding("utf-8");
            String fileName = URLEncoder.encode("医生模板下载", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            EasyExcel.write(response.getOutputStream()).withTemplate(templateFileName).sheet().doWrite(null);

            JSONObject jsonObject = new JSONObject();
            return success(jsonObject);
        } catch (Exception e) {
            return anomalous(getExceptionMsg(e));
        }
    }



    @RequestMapping(value = "Import", method = RequestMethod.POST)
    public MyResult Import(@RequestParam("file") MultipartFile file,
                           @RequestParam("timeStr") String timeStr,
                           @RequestParam("sign") String sign,
                           @RequestParam("staffCode") String staffCode) {

        try {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("file",file);
            jsonObject.put("staffCode",staffCode);

            PreCheck preCheck =checkSignAdmInterface(timeStr, sign,staffCode,"/ImportExcel/Import");
            if(preCheck.getError()==1){
                return failed(preCheck.getMessage());
            }


            if (file.isEmpty()) {
                return failed("文件不存在");
            }

            String fileName = file.getOriginalFilename();
            if(!isFile(fileName)){
                return failed("非正确的文件格式不能上传");
            }

            File file1 = new File(path);
            if (!file1.exists()) {
                file1.mkdirs();
            }
            String fdPath = filesRootPath+"\\"+staffCode;
            File fd =new File(fdPath);
            if(!fd.exists()){
                fd.mkdirs();
            }

            String suffix = getSuffix(fileName);
            String filePath11 = fdPath + "\\" +  getTimeStr() + suffix;
            File dest =new File(filePath11);
            try {
                file.transferTo(dest);
            } catch (Exception e) {
                return failed("上传失败:"+e.getMessage());
            }


            String uuid = UUID.randomUUID().toString();

            Thread t =new Thread(new Runnable() {
                @Override
                public void run() {

                    try {

                        String filePath = path +"\\"+ uuid + ".txt";
                        String content1 = "0";
                        saveAsFileWriter(filePath, content1);

                        String content2="3";

                        try {
                            MultipartFile file2 = getMulFileByPath(filePath11);
                            InputStream is = file2.getInputStream();
                            String fileName = file.getOriginalFilename();

                            MyResult myResult = batchImportNew(fileName, staffCode,is);

                            if(myResult.getError()==0){
                                String content3 = "1";
                                saveAsFileWriter(filePath, content3);
                            }else if(myResult.getError()==1){
                                content2 = myResult.getMessage();
                                saveAsFileWriter(filePath, content2);
                            }

                        } catch (Exception e) {
                            content2 = "2";
                            insertError("/ImportExcel/Import", "file", getExceptionMsg(e), "api");
                            saveAsFileWriter(filePath, content2);
                        }

                    } catch (Exception e) {
                        insertError("/ImportExcel/Import", "file", getExceptionMsg(e), "api");
                    }

                }
            });
            t.start();

            return success(uuid);
        } catch (Exception e) {
            return anomalous(e.getMessage());
        }
    }


    @RequestMapping(value = "IsSuccess", method = RequestMethod.POST)
    public MyResult IsSuccess(@RequestBody JSONObject jsonObject) {
        try {

            String uuid = jsonObject.getString("uuid");

            StringBuffer buffer = new StringBuffer();
            BufferedReader bf = new BufferedReader(new FileReader(path+"\\" + uuid + ".txt"));
            String s = null;
            while ((s = bf.readLine()) != null) {//使用readLine方法，一次读一行
                buffer.append(s.trim());
            }
            bf.close();
            String b = buffer.toString();
            if(b.equals("1")){
                File file = new File(path+"\\" + uuid + ".txt");
                file.delete();
            }

            return success(b);
        } catch (IOException e) {
            insertError("/ImportExcel/IsSuccess", jsonObject.toJSONString(), getExceptionMsg(e), "api");
            return anomalous(getExceptionMsg(e));
        }

    }



    private static MultipartFile getMulFileByPath(String picPath) {
        FileItem fileItem = createFileItem(picPath);
        MultipartFile mfile = new CommonsMultipartFile(fileItem);
        return mfile;
    }

    private static FileItem createFileItem(String filePath) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "textField";
        int num = filePath.lastIndexOf(".");
        String extFile = filePath.substring(num);
        FileItem item = factory.createItem(textFieldName, "text/plain", true,
                "MyFileName" + extFile);
        File newfile = new File(filePath);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        try
        {
            FileInputStream fis = new FileInputStream(newfile);
            OutputStream os = item.getOutputStream();
            while ((bytesRead = fis.read(buffer, 0, 8192))
                    != -1)
            {
                os.write(buffer, 0, bytesRead);
            }
            os.close();
            fis.close();
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        return item;
    }


    @Autowired
    private NurseAideMapper nurseAideMapper;

    @Autowired
    private StaffMapper staffMapper;

    @Autowired
    private UserMapper userMapper;


    private final static char[] VERIFY_CODE = { '1', '0', 'X', '9', '8', '7',
            '6', '5', '4', '3', '2' }; // 18位身份证中最后一位校验码

    private final static int[] VERIFY_CODE_WEIGHT = { 7, 9, 10, 5, 8, 4, 2, 1,
            6, 3, 7, 9, 10, 5, 8, 4, 2 };// 18位身份证中，各个数字的生成校验码时的权值


    //不验证手机号重复
    private MyResult batchImportNew(String fileName, String staffCode,
                                    InputStream is) throws Exception {

//        List<User> userList = new ArrayList<>();
//        List<NurseAide> listNurseAide = new ArrayList<>();
//
//        Staff staff = staffMapper.getByStaffCode(staffCode);
//
//        InstitutionStaffRel institutionStaffRel = institutionStaffRelService.getByStaffCode(staffCode);
//        String insCode = institutionStaffRel.getInstitutionCode();
//
//        String roleCode = staff.getRoleCode();
//        if (roleCode == null) {
//            return MyResult.Failed("该角色不存在");
//        }
//
//        if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
//            throw new Exception("上传文件格式不正确");
//        }
//
//        boolean isExcel2003 = true;
//        if (fileName.matches("^.+\\.(?i)(xlsx)$")) {
//            isExcel2003 = false;
//        }
//
//
//        Workbook wb = null;
//        if (isExcel2003) {
//            wb = new HSSFWorkbook(is);
//        } else {
//            wb = new XSSFWorkbook(is);
//        }
//
//        Sheet sheet = wb.getSheetAt(0);
//        if (sheet == null) {
//            return MyResult.Failed("文件不存在！");
//        }
//
//
//
//        HashMap<String,String> idCardHashMap =new HashMap<>();
//
//        String repetitionIdCard="";
//        String errorName="";
//        String errorPhone="";
//        String errorIdCard="";
//        String errorHomeAddress="";
//        String errorElderlyClass="";
//        String errorZone="";
//
//        for (int r = 1; r <= sheet.getLastRowNum(); r++) {
//
//            if(r==1){
//                continue;
//            }
//
//            Row row = sheet.getRow(r); //通过sheet表单对象 得到 行对象
//
//            if (row == null) {
//                continue;
//            }
//
//            for (int cellIndex = 0; cellIndex <= row.getLastCellNum(); cellIndex++) {
//                if (row.getCell(cellIndex) == null) {
//                    continue;
//                }
//            }
//
//
//            boolean isError=false;
//
//            if(row.getCell(0)==null){
//                continue;
//            }
//
//            //name
//            row.getCell(0).setCellType(Cell.CELL_TYPE_STRING);//第1格
//            String elderlyName = row.getCell(0).getStringCellValue().replace(" ", "");//得到每一行第一个单元格的值
//            if (elderlyName == null || elderlyName.isEmpty()) {
//                isError=true;
//                errorName=errorName.length()>0?errorName+"、"+(r + 1):(r + 1)+"";
//            }
//
//            //phone
//            row.getCell(1).setCellType(Cell.CELL_TYPE_STRING); //第2格
//            String phone = row.getCell(1).getStringCellValue().replace(" ", "");
//            if (phone.trim().length() != 11) {
//                isError=true;
//                errorPhone=errorPhone.length()>0?errorPhone+"、"+(r + 1):(r + 1)+"";
//            }
//
//            //idCard
//            row.getCell(2).setCellType(Cell.CELL_TYPE_STRING);//第3格
//            String idCard = row.getCell(2).getStringCellValue().replace(" ", "");
//            if (!check(idCard)) {
//                isError=true;
//                errorIdCard=errorIdCard.length()>0?errorIdCard+"、"+(r + 1):(r + 1)+"";
//            }
//
//
//            //address
//            row.getCell(3).setCellType(Cell.CELL_TYPE_STRING); //第4格
//            String homeAddress = row.getCell(3).getStringCellValue();
//
//
//            if(!idCardHashMap.containsKey(idCard)){
//                idCardHashMap.put(idCard,idCard);
//            }else {
//                isError=true;
//                repetitionIdCard=repetitionIdCard.equals("")?idCard:repetitionIdCard+"、"+idCard;
//            }
//
//
//            if(isError){
//                continue;
//            }
//
//
//            Date dateNow = new Date();
//
//            NurseAide nurseAide = new NurseAide();
//            nurseAide.setNurseAideCode(UUID.randomUUID().toString());
//            nurseAide.setUserCode(UUID.randomUUID().toString());
//            nurseAide.setIdCard(idCard);
//            nurseAide.setInstitutionCode(insCode);
//            nurseAide.setCreateTime(dateNow);
//            nurseAide.setAddress(homeAddress);
//            listNurseAide.add(nurseAide);
//
//            User user = new User();
//            user.setUserCode(nurseAide.getUserCode());
//            user.setLoginName(idCard);
//            user.setPhone(phone);
//            user.setPassword(getMD5Str(phone.substring(5, 11)));
//            user.setName(elderlyName);
//            user.setStatus(1);
//            user.setCreateTime(dateNow);
//            user.setUserType(9);
//            user.setGovernmentCode(staff.getGovernmentCode());
//            user.setInstitutionCode(insCode);
//            userList.add(user);
//
//        }
//
//
//        if(!errorName.equals("")||!errorPhone.equals("")||!errorIdCard.equals("")||!errorHomeAddress.equals("")||!errorElderlyClass.equals("")||!errorZone.equals("")){
//            return MyResult.Failed("表格中姓名格式不正确：第"+errorName+"行" +
//                    "<br>表格中有格式不正确的手机号码：第"+errorPhone+"行" +
//                    "<br>表格中有格式不正确的身份证：第"+errorIdCard+"行" +
//                    "<br>表格中有家庭地址为空：第"+errorHomeAddress+"行" +
//                    "<br>表格中有不存在的老人类别：第"+errorElderlyClass+"行"+
//                    "<br>表格中有不存在的所属区域：第"+errorZone+"行");
//        }
//
//
//        String databasePhone="";
//        String databaseIdCard="";
//
//        if(listNurseAide.size() == 0){
//            return MyResult.Success("上传成功");
//        }
//
//        int index = listNurseAide.size() / 500;
//        for (int i=0;i< index+1;i++) {
//
//            List<NurseAide> elderlyList1= listNurseAide.stream().skip(i * 500).limit(500).collect(Collectors.toList());
//
//            List<String> idcardList = nurseAideMapper.batchSelectIdCard(elderlyList1);
//            for(String idcard :idcardList){
//                databaseIdCard=databaseIdCard+"、"+idcard;
//            }
//
////            List<String> phoneList = userMapper.batchSelectPhone(elderlyList1);
////            for(String phone :phoneList){
////                databasePhone=databasePhone+"、"+phone;
////            }
//
//        }
////        if(!databasePhone.equals("")||!databaseIdCard.equals("")){
////            return MyResult.Failed("手机号码已注册："+databasePhone+",<br>身份证号码已注册："+databaseIdCard);
////        }
//        if(!databaseIdCard.equals("")){
//            return MyResult.Failed("身份证号码已注册："+databaseIdCard);
//        }
//
//
//        for (int i=0;i< index+1;i++) {
//            //stream流表达式，skip表示跳过前i*10000条记录，limit表示读取当前流的前10000条记录
//            nurseAideMapper.batchInsert(listNurseAide.stream().skip(i * 500).limit(500).collect(Collectors.toList()));
//            userMapper.batchInsert(userList.stream().skip(i * 500).limit(500).collect(Collectors.toList()));
//        }

        return MyResult.Success("上传成功");
    }

    //身份证号验证
    public static boolean check(String cardNumber){
        if (null != cardNumber){
            cardNumber = cardNumber.trim();
            if (15 == cardNumber.length()){
                cardNumber = contertToNewCardNumber(cardNumber);
            }
            return validate(cardNumber);
        }
        return false;
    }

    public static boolean validate(String cardNumber){
        boolean result = true;
        result = result && (null != cardNumber); // 身份证号不能为空
        result = result && 18 == cardNumber.length(); // 身份证号长度是18(新证)
        // 身份证号的前17位必须是阿拉伯数字
        for (int i = 0; result && i < 18 - 1; i++){
            char ch = cardNumber.charAt(i);
            result = result && ch >= '0' && ch <= '9';
        }
        // 身份证号的第18位校验正确
        result = result
                && (calculateVerifyCode(cardNumber) == cardNumber
                .charAt(18 - 1));
        // 出生日期不能晚于当前时间，并且不能早于1900年
        try{
            Date birthDate = new SimpleDateFormat("yyyyMMdd")
                    .parse(getBirthDayPart(cardNumber));
            result = result && null != birthDate;
            result = result && birthDate.before(new Date());
            result = result && birthDate.after(new Date(-2209017600000L));
            /**
             * 出生日期中的年、月、日必须正确,比如月份范围是[1,12],
             * 日期范围是[1,31]，还需要校验闰年、大月、小月的情况时，
             * 月份和日期相符合
             */
            String birthdayPart = getBirthDayPart(cardNumber);
            String realBirthdayPart = new SimpleDateFormat("yyyyMMdd")
                    .format(birthDate);
            result = result && (birthdayPart.equals(realBirthdayPart));
        }catch(Exception e){
            result = false;
        }
        return result;
    }

    private static String getBirthDayPart(String cardNumber){
        return cardNumber.substring(6, 14);
    }

    /**
     * 校验码（第十八位数）：
     *
     * 十七位数字本体码加权求和公式 S = Sum(Ai * Wi), i = 0...16 ，先对前17位数字的权求和；
     * Ai:表示第i位置上的身份证号码数字值 Wi:表示第i位置上的加权因子 Wi: 7 9 10 5 8 4 2 1 6 3 7 9 10 5 8 4
     * 2; 计算模 Y = mod(S, 11)< 通过模得到对应的校验码 Y: 0 1 2 3 4 5 6 7 8 9 10 校验码: 1 0 X 9
     * 8 7 6 5 4 3 2
     *
     * @param cardNumber
     * @return
     */
    private static char calculateVerifyCode(CharSequence cardNumber){
        int sum = 0;
        for (int i = 0; i < 18 - 1; i++){
            char ch = cardNumber.charAt(i);
            sum += ((int) (ch - '0')) * VERIFY_CODE_WEIGHT[i];
        }
        return VERIFY_CODE[sum % 11];
    }

    /**
     * 把15位身份证号码转换到18位身份证号码<br>
     * 15位身份证号码与18位身份证号码的区别为：<br>
     * 1、15位身份证号码中，"出生年份"字段是2位，转换时需要补入"19"，表示20世纪<br>
     * 2、15位身份证无最后一位校验码。18位身份证中，校验码根据根据前17位生成
     *
     * @param
     * @return
     */
    private static String contertToNewCardNumber(String oldCardNumber){
        StringBuilder buf = new StringBuilder(18);
        buf.append(oldCardNumber.substring(0, 6));
        buf.append("19");
        buf.append(oldCardNumber.substring(6));
        buf.append(calculateVerifyCode(buf));
        return buf.toString();
    }



}
